import { ProjectConfig } from '#/config';
import { PermissionModeEnum } from '@/enums/appEnum';
import { AppStorage, PermissionService, PermissionStorage, UserStorage } from '@2/app/core/ioc';
import { useMultipleTabStore } from '@/store/modules/multipleTab';
import { resetRouter, router } from '@/router';
import { RouteRecordRaw } from 'vue-router';
import { useTabs } from '@/hooks/web/useTabs';
import { RoleEnum } from '@/enums/roleEnum';
import { isArray } from '@/utils/is';
import { intersection } from 'lodash-es';
import projectSetting from '@/settings/projectSetting';

const { closeAll } = useTabs(router);
/**
 * @program: microservice-central-portal
 * @description: 针对页面安全访问控制类，用于控制用户访问权限，包括菜单权限、按钮权限、数据权限等等。
 * @author: baiHoo.chen
 * @create: 2022年5月26日
 **/
export class Security {
  /**
   * 切换权限模式
   */
  public static togglePermissionMode() {
    AppStorage.setProjectConfig({
      permissionMode:
        (AppStorage.getProjectConfig() as ProjectConfig).permissionMode === PermissionModeEnum.BACK
          ? PermissionModeEnum.ROUTE_MAPPING
          : PermissionModeEnum.BACK,
    });
    location.reload();
  }
  /**
   * 重置和重新获得权限资源信息
   */
  public static async resume() {
    const tabStore = useMultipleTabStore();
    tabStore.clearCacheTabs();
    resetRouter();

    // 动态加载路由（再次）
    const routes = await PermissionService.buildRoutesAction();
    routes.forEach((route) => {
      router.addRoute(route as unknown as RouteRecordRaw);
    });

    PermissionStorage.setLastBuildMenuTime();
    await closeAll();
  }

  /**
   * 判断是否有权限
   * @param value 权限值
   * @param def 默认值
   */
  public static hasPermission(
    value?: RoleEnum | RoleEnum[] | string | string[],
    def = true,
  ): boolean {
    // Visible by default
    if (!value) {
      return def;
    }
    const permMode = (AppStorage.getProjectConfig() as ProjectConfig).permissionMode;
    const perms = UserStorage.getAppUser().permissions as RoleEnum[];
    let roles = UserStorage.getAppUser().roles.map((r) => r.code) as RoleEnum[];
    roles = roles.concat(perms);
    if ([PermissionModeEnum.ROUTE_MAPPING, PermissionModeEnum.ROLE].includes(permMode)) {
      if (!isArray(value)) {
        return roles.includes(value as RoleEnum);
      }
      return (intersection(value, roles) as RoleEnum[]).length > 0;
    }

    if (PermissionModeEnum.BACK === permMode) {
      const allCodeList = PermissionStorage.getAuthorities() as string[];
      if (!isArray(value)) {
        const splits = ['||', '&&'];
        const splitName = splits.find((item) => value.includes(item));
        if (splitName) {
          const splitCodes = value.split(splitName);
          return splitName === splits[0]
            ? intersection(splitCodes, allCodeList).length > 0
            : intersection(splitCodes, allCodeList).length === splitCodes.length;
        }
        return allCodeList.includes(value);
      }
      return (intersection(value, allCodeList) as string[]).length > 0;
    }
    return true;
  }
  /**
   * 切换角色
   * @param roles
   */
  public static async changeRole(roles: RoleEnum | RoleEnum[]): Promise<void> {
    if (projectSetting.permissionMode !== PermissionModeEnum.ROUTE_MAPPING) {
      throw new Error(
        'Please switch PermissionModeEnum to ROUTE_MAPPING mode in the configuration to operate!',
      );
    }

    if (!isArray(roles)) {
      roles = [roles];
    }
    UserStorage.getAppUser().permissions = roles;
    await this.resume();
  }

  /**
   * 刷新菜单
   */
  public static async refreshMenu() {
    await this.resume();
  }
}
